package cn.dengta.webapp.trade.entity;

import java.math.BigDecimal;
import javax.annotation.Nullable;

import cn.dengta.common.model.Status;
import cn.dengta.webapp.base.entity.BaseEntity;
import cn.dengta.webapp.base.entity.TimeBasedEntity;
import cn.dengta.webapp.trade.model.*;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.experimental.Accessors;
import me.codeplayer.util.*;

/**
 * 积分流水记录表
 *
 * @author yuqidi
 * @since 2022-03-18
 */
@Setter
@Getter
@Accessors(chain = true)
@TableName("tr_user_integral_log")
public class UserIntegralLog extends TimeBasedEntity {

	/** 用户ID */
	protected Long userId;
	/** 资金流向：1=收入；0=不变；-1=支出 Flow */
	protected Integer flow;
	/** 交易方：1=from；2=to Side */
	protected Integer side;
	/** 业务类型 */
	protected String tradeType;
	/** 钻石收益来源类型 */
	protected String coinTradeType;
	/** 总的交易额度=rechargeAmount + freeAmount */
	protected BigDecimal tradeAmount;
	/** 充值钻部分所得积分 */
	protected BigDecimal rechargeAmount;
	/** 免费钻部分所得积分 */
	protected BigDecimal freeAmount;
	/** 资金积分 */
	protected BigDecimal totalAmount;
	/** 可用积分 */
	protected BigDecimal activeAmount;
	/** 冻结积分 */
	protected BigDecimal frozenAmount;
	/** 目标用户ID */
	protected Long toUserId;
	/** Ai标识 */
	protected Long aiId;
	/** 关联目标类型 */
	protected String assocType;
	/** 关联目标ID */
	protected Long assocId;
	/** 备注 */
	protected String remark;
	/** 关联【消费者】的钻石日志记录（便于反查） */
	@Nullable
	protected Long toUserCoinLogId;
	/** 添加IP */
	protected String addIp;
	/** 一级推广员 */
	protected Long agentId;
	/** 二级推广员 */
	protected Long agent2Id;
	/** 直播ID */
	protected Long liveId;
	/** 代理奖励ID */
	protected Long agentRewardId;
	/** 邀请人ID */
	protected Long inviteUserId;
	/** 邀请奖励ID */
	protected Long inviteRewardId;
	/** 处理状态 */
	protected Integer handleStatus;
	/** 交易的钻石组成 */
	protected String coinForm;
	/** 是否已再利用: 0=没有(默认);1=已使用 */
	protected Integer useStatus;

	protected transient BaseEntity assocObj;
	protected transient String subject;

	public UserIntegralLog() {

	}

	public static UserIntegralLog trade(TradeType tradeType, final boolean fromOrTo, final UserIntegral account, final BigDecimal tradeAmount) {
		final TradeTypeCore core = fromOrTo ? tradeType.getFrom() : tradeType.getTo();
		final UserIntegralLog log = new UserIntegralLog(account, tradeAmount, core);
		log.setTradeType(tradeType.getValue());
		log.setSide(Side.of(fromOrTo).getValue());
		log.setFlow(core.getFlow().getValue());
		return log;
	}

	/**
	 * 初始化
	 *
	 * @param account 账户
	 * @param changeAmount 改变额度
	 * @param core 核心交易枚举
	 */
	public UserIntegralLog(UserIntegral account, BigDecimal changeAmount, TradeTypeCore core) {
		this.tradeAmount = core.isConsume() ? changeAmount.negate() : changeAmount;
		this.totalAmount = account.opTotalAmount(core.operators[0], changeAmount);
		this.activeAmount = account.opActiveAmount(core.operators[1], changeAmount);
		this.frozenAmount = account.opFrozenAmount(core.operators[2], changeAmount);
	}

	public TradeType getTradeTypeE() {
		return TradeType.of(tradeType);
	}

	public String getTradeType_() {
		return X.map(getTradeTypeE(), TradeType::getLabel);
	}

	public TradeTypeCore getCoreType() {
		return X.map(getTradeTypeE(), t -> t.getCoreType(side));
	}

	public char getSign() {
		return getCoreType().getSign();
	}

	public void handleAssocObject(BaseEntity obj) {
		this.assocObj = obj;
		this.assocType = obj.entityName();
		this.assocId = obj.getId();
	}

	public void assocCoinForm(UserIntegralLog.CoinForm coinForm) {
		if (coinForm != null) {
			this.coinForm = JSONUtil.encode(coinForm);
		}
	}

	public void assocCoinForm(Integer recharge, Integer free) {
		this.coinForm = JSONUtil.encode(new CoinForm(recharge, free));
	}

	public boolean hasUse() {
		return Status.NO.eq(this.useStatus) && System.currentTimeMillis() < this.getAddTime().getTime() + EasyDate.MILLIS_OF_DAY * 2;
	}

	@Getter
	@Setter
	@NoArgsConstructor
	@AllArgsConstructor
	public static class CoinForm {

		/** 充值钻 */
		private Integer recharge;
		/** 活动钻 */
		private Integer free;

	}

	public static final String USER_ID = "user_id";
	public static final String FLOW = "flow";
	public static final String SIDE = "side";
	public static final String TRADE_TYPE = "trade_type";
	public static final String COIN_TRADE_TYPE = "coin_trade_type";
	public static final String TRADE_AMOUNT = "trade_amount";
	public static final String TOTAL_AMOUNT = "total_amount";
	public static final String ACTIVE_AMOUNT = "active_amount";
	public static final String FROZEN_AMOUNT = "frozen_amount";
	public static final String TO_USER_ID = "to_user_id";
	public static final String ASSOC_TYPE = "assoc_type";
	public static final String ASSOC_ID = "assoc_id";
	public static final String AGENT_ID = "agent_id";
	public static final String AGENT2_ID = "agent2_id";
	public static final String LIVE_ID = "live_id";
	public static final String TO_USER_COIN_LOG_ID = "to_user_coin_log_id";
	public static final String HANDLE_STATUS = "handle_status";
	public static final String REMARK = "remark";
	public static final String ADD_IP = "add_ip";
	public static final String USE_STATUS = "use_status";

}
